#include	"a_global_vars.h"
#include	"config_parser.h"

int PACK_ID = 0, nextProp = 0, currentFill = 0, propLIMIT = -1;
bool currentFilled = false;
int msg_counter = 0;
proposer_msg *p_msg;

//------------------------------------------------------------------------------
void acceptor_0_recv_msg(int sd, short event, void * arg) {

	UNUSED_ARG(event);
	UNUSED_ARG(arg);

	int status = recv(sd, p_msg, sizeof(proposer_msg), MSG_WAITALL);
	assert(status == sizeof(proposer_msg));
	a_interval_performance->interval_bytes_received += status;
	//printf("a_hd: %d %d\n", a_interval_performance->highest_deliverable_inst_id , p_msg->highest_deliverable_inst_id);
	assert(a_interval_performance->highest_deliverable_inst_id <= p_msg->highest_deliverable_inst_id);
	a_interval_performance->highest_deliverable_inst_id = p_msg->highest_deliverable_inst_id;
	learner_deliver();
	generate_instance(p_msg);
	a_interval_performance->interval_num_packets_proposer_to_acceptor_0++;

	//paxos_instances[(short_decision->instance_id % INTERNAL_BUFFER_SIZE)].vval = data[(short_decision->instance_id % INTERNAL_BUFFER_SIZE)].packet.pack_id;
	//printf("HD: %d MSG_ID: %d\n", a_interval_performance->highest_deliverable_inst_id, p_msg->msg_id);

}
void generate_instance(proposer_msg *pm) {

	memcpy(&data[(currentFill % INTERNAL_BUFFER_SIZE)].packet.p_msgs[0], pm, sizeof(proposer_msg));
	msg_counter = 0;
	propLIMIT = currentFill;
	PACK_ID++;
	data[(currentFill % INTERNAL_BUFFER_SIZE)].packet.pack_id = PACK_ID;
	data[(currentFill % INTERNAL_BUFFER_SIZE)].deliver = false;
	data[(currentFill % INTERNAL_BUFFER_SIZE)].received = false;
	data[(currentFill % INTERNAL_BUFFER_SIZE)].instance_id = currentFill;
	data[(currentFill % INTERNAL_BUFFER_SIZE)].coordinator_id = COORDINATOR_ID;
	data[(currentFill % INTERNAL_BUFFER_SIZE)].dec = -1;
	data[(currentFill % INTERNAL_BUFFER_SIZE)].round_number = 1;// =0
	data[(currentFill % INTERNAL_BUFFER_SIZE)].packet.p_msgs[0].num_nodes_visited++;

	currentFill++;
	a_interval_performance->total_num_instances++;
}

void prepare_fresh_instances_timer_event(int sd, short event, void * arg) {

	a_interval_performance->interval_num_entrance++;

	int counter = 0;
	while (counter < SUBMIT_PER_WAKE && nextProp <= propLIMIT) {
		data[(nextProp % INTERNAL_BUFFER_SIZE)].highestDeliverable = a_interval_performance->highest_deliverable_inst_id;
		data[(nextProp % INTERNAL_BUFFER_SIZE)].received = true;

		send_inst_paxos_to_successor((nextProp % INTERNAL_BUFFER_SIZE));
		//gapEnd = nextProp;
		a_interval_performance->interval_num_packets_sent++;
		counter++;
		nextProp++;
	}
	evtimer_add(inst_propose_timeout_eve, &tv1);
}
void send_inst_paxos_to_successor(int nextMulticast) {
	rtag = true;
	inst_paxos inst_paxos_msg;

	inst_paxos_msg.inst_packet = data[nextMulticast];
	inst_paxos_msg.inst_packet.received = false;
	inst_paxos_msg.type = 'n';

	if (inst_paxos_msg.inst_packet.packet.p_msgs[0].msg_id != 0)
		coordinator_execute_phase_2_a(inst_paxos_msg.inst_packet.instance_id, inst_paxos_msg.inst_packet.round_number, &inst_paxos_msg.paxos_2b);

	inst_paxos_msg.inst_packet.highestDeliverable = a_interval_performance->highest_deliverable_inst_id;
	int status = send((get_config_info()->server_infos[get_config_info()->self_acceptor_id].successor_sid), &inst_paxos_msg, sizeof(inst_paxos), MSG_WAITALL);
	assert(status == sizeof(inst_paxos));
	a_interval_performance->interval_bytes_sent += status;
}

